package com.zhangxiaoxiang.ko.core.util;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ObjUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * KO:类似Optional类型的if工具类<p/>
 * 命名为KO缘由:KO在键盘上紧挨着,方便敲击,如果不好记,可以理解为 kailin Optional 首字母简称哈哈哈,目的就是尽量KO(击倒)一些if
 * 配合hutool的 (对JDK的Optional一些新特性移植和增强)
 * 内部KO可以互相调用自己的方法,但是这里为了各个方法独立,内部暂时不互相调,凑代码行数哈
 *
 * @author zhangxiaoxiang
 * @see cn.hutool.core.lang.Opt
 * @since 2023/8/20
 */
@Slf4j
public class KO {

    // 异常类型方法----------------------------------------------------------------------------------------------

    /**
     * 满足条件直接抛异常
     *
     * @param rule             条件判断
     * @param runtimeException 异常类型
     * @param <RE>             异常
     */
    public static <RE extends RuntimeException> void thenThrow(boolean rule, RE runtimeException) {
        if (rule) {
            throw runtimeException;
        }
    }

    /**
     * 直接抛出业务异常
     *
     * @param kbExceptionMsg 业务异常
     */
    public static void throwKbException(String kbExceptionMsg) {
        throw new RuntimeException(kbExceptionMsg);
    }

    /**
     * 满足条件直接抛异常
     *
     * @param rule           条件判断[true,则继续后续操作]
     * @param kbExceptionMsg 业务异常描述
     */
    public static void thenThrow(boolean rule, String kbExceptionMsg) {
        if (rule) {
            throw new RuntimeException(kbExceptionMsg);
        }
    }

    /**
     * 满足条件直接抛异常[顺便打印日志]
     *
     * @param rule         条件判断[true,则继续后续操作]
     * @param exceptionMsg 业务异常描述信息
     * @param exceptionMeg 带占位符的描述 eg: "用户id为:{},工号为:{}"
     * @param argArray     占位参数 eg 123456,804000
     */
    public static void thenThrow(boolean rule, String exceptionMsg, String exceptionMeg, final Object... argArray) {
        if (rule) {
            log.info("{}", StrFormatter.format(exceptionMeg, argArray));
            throw new RuntimeException(exceptionMsg);
        }
    }


    // 业务函数类型----------------------------------------------------------------------------------------------------

    /**
     * 满足条件就执行一个消费函数Consumer
     *
     * @param rule     条件
     * @param t        入参
     * @param consumer 消费函数
     * @param <T>      入参类型
     */
    public static <T> void thenConsumer(boolean rule, Consumer<T> consumer, T t) {
        if (rule) {
            consumer.accept(t);
        }
    }

    /**
     * 满足条件就执行一个Runnable
     *
     * @param rule     条件
     * @param runnable 执行一个操作
     */
    public static void thenRunnable(boolean rule, Runnable runnable) {
        if (rule) {
            runnable.run();
        }
    }

    /**
     * 满足条件就执行一个Runnable
     *
     * @param rule     条件
     * @param runnable 执行一个操作
     */
    public static void thenOrRunnable(boolean rule, Runnable runnable) {
        if (rule) {
            runnable.run();
        }
    }

    /**
     * 满足条件就执行一个Runnable
     *
     * @param rule     条件
     * @param runnable 执行一个操作
     */
    public static <T> void thenFunc0(boolean rule, Supplier<T> runnable) {
        if (rule) {
            runnable.get();
        }
    }

    /**
     * 满足条件就执行一个Function
     *
     * @param rule     条件
     * @param function 执行一个操作
     * @param <T>      入参类型
     */
    public static <T> void thenFunction(boolean rule, Function<T, ?> function, T t) {
        if (rule) {
            function.apply(t);
        }
    }

    // 常用高频方法[主要使用hutool处理]---------------------------------------------------------------------------


    /**
     * 满足条件直接抛异常
     *
     * @param object         charSequence
     * @param kbExceptionMsg 异常描述
     */
    public static void isNullThenThrow(Object object, String kbExceptionMsg) {
        if (ObjUtil.isNull(object)) {
            throw new RuntimeException(kbExceptionMsg);
        }
    }

    /**
     * 满足条件直接抛异常
     *
     * @param collection     charSequence
     * @param kbExceptionMsg 异常描述
     */
    public static void isEmptyThenThrow(Collection<?> collection, String kbExceptionMsg) {
        if (CollUtil.isEmpty(collection)) {
            throw new RuntimeException(kbExceptionMsg);
        }
    }

    /**
     * 满足条件直接抛异常
     *
     * @param predicate      charSequence
     * @param kbExceptionMsg 异常描述
     */
    public static <T> void isPredicateThenThrow(T t, Predicate<T> predicate, String kbExceptionMsg) {
        if (predicate.test(t)) {
            throw new RuntimeException(kbExceptionMsg);
        }
    }

    /**
     * if else造型
     *
     * @param rule           条件
     * @param runnable       满足执行
     * @param orElseRunnable 不满足执行
     */
    public static void thenOrElse(boolean rule, Runnable runnable, Runnable orElseRunnable) {
        if (rule) {
            runnable.run();
        } else {
            orElseRunnable.run();
        }
    }


}
